from flask import Flask, render_template, request, redirect, url_for, session, jsonify, flash
from datetime import datetime, timedelta
import mysql.connector
from docx import Document
import os

app = Flask(__name__)
app.secret_key = 'your_secret_key'
app.config['UPLOAD_FOLDER'] = 'uploads'
app.config['ALLOWED_EXTENSIONS'] = {'docx'}

# 模拟的用户数据，包括班级信息
users = {
    'teacher': [],
    'student': [],
    'parent': []
}

# 模拟的班级数据
classes = {}

# 模拟考试数据
exams = {}
cheating_records = {}  # 记录作弊次数


# 允许的文件类型
def allowed_file(filename):
    return '.' in filename and filename.rsplit('.', 1)[1].lower() in app.config['ALLOWED_EXTENSIONS']


# 解析 .docx 文件中的考试题目
def extract_questions(file_path, question_type):
    document = Document(file_path)
    questions = []
    current_question = None

    for para in document.paragraphs:
        text = para.text.strip()

        if question_type == 'questionsxuanze':  # 选择题
            if text.startswith("Q:"):
                if current_question:
                    questions.append(current_question)
                current_question = {
                    'text': text[2:].strip(),
                    'options': {'A': None, 'B': None, 'C': None, 'D': None},
                    'correct_answer': None
                }
            elif any(option in text for option in ['A:', 'B:', 'C:', 'D:']):
                # 识别同一行的选项
                options = text.split(' ')
                for option in options:
                    if option.startswith('A:'):
                        current_question['options']['A'] = option[2:].strip()
                    elif option.startswith('B:'):
                        current_question['options']['B'] = option[2:].strip()
                    elif option.startswith('C:'):
                        current_question['options']['C'] = option[2:].strip()
                    elif option.startswith('D:'):
                        current_question['options']['D'] = option[2:].strip()
            elif text.startswith("Answer:"):
                if current_question:
                    current_question['correct_answer'] = text[7:].strip()
            if current_question and all(current_question['options'].values()):
                questions.append(current_question)

        elif question_type == 'question2':  # 判断题
            if text.startswith("Q:"):
                if current_question:
                    questions.append(current_question)
                current_question = {
                    'text': text[2:].strip(),
                    'correct_answer': None
                }
            elif text.startswith("答案:"):
                if current_question:
                    answer_text = text[3:].strip()
                    if answer_text in ['对', '错']:
                        current_question['correct_answer'] = answer_text

        elif question_type == 'questions':  # 主观题
            if text and (text[0].isdigit() and text[1] == '.'):
                if current_question:
                    questions.append(current_question)
                current_question = {'text': text, 'answers': []}
            elif text:
                if current_question:
                    current_question['answers'].append(text)

    if current_question:
        questions.append(current_question)

    return questions


# 将题目插入到数据库
def insert_questions(exam_name, questions, question_type):
    conn = mysql.connector.connect(
        host="152.136.49.229",
        user="yuyu",
        password="123456",
        database="yuyude"
    )
    cursor = conn.cursor()

    try:
        # 插入试卷信息
        sql = "INSERT INTO exams (name) VALUES (%s)"
        cursor.execute(sql, (exam_name,))
        exam_id = cursor.lastrowid

        for question in questions:
            if question_type == 'questionsxuanze':  # 选择题
                sql = """
                INSERT INTO questionsxuanze (exam_id, question_text, a, b, c, d, correct_answer)
                VALUES (%s, %s, %s, %s, %s, %s, %s)
                """
                values = (
                    exam_id, question['text'],
                    question['options']['A'], question['options']['B'],
                    question['options']['C'], question['options']['D'],
                    question['correct_answer']
                )
            elif question_type == 'question2':  # 判断题
                sql = """
                INSERT INTO question2 (exam_id, question_text, correct_answer)
                VALUES (%s, %s, %s)
                """
                values = (exam_id, question['text'], question['correct_answer'])
            elif question_type == 'questions':  # 主观题
                sql = """
                INSERT INTO questions_and_answers (exam_name, question_text, answer_text)
                VALUES (%s, %s, %s)
                """
                for answer in question['answers']:
                    values = (exam_name, question['text'], answer)
                    cursor.execute(sql, values)
                    continue

            cursor.execute(sql, values)

        conn.commit()
    except mysql.connector.Error as err:
        print(f"Error: {err}")
        conn.rollback()
    finally:
        cursor.close()
        conn.close()


# 登录
@app.route('/', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        user_type = request.form['user_type']
        username = request.form['username']
        password = request.form['password']

        if user_type in users:
            for user in users[user_type]:
                if user['username'] == username and user['password'] == password:
                    session['username'] = username
                    session['user_type'] = user_type
                    if user_type == 'student':
                        return redirect(url_for('student_dashboard', username=username))
                    elif user_type == 'teacher':
                        return redirect(url_for('teacher_dashboard', username=username))
                    elif user_type == 'parent':
                        return redirect(url_for('parent_dashboard', username=username))
        return "登录失败，用户名或密码错误！"

    return render_template('login.html')


@app.route('/register', methods=['GET', 'POST'])
def register():
    if request.method == 'POST':
        user_type = request.form['user_type']
        username = request.form['username']
        machine_id = request.form['machine_id']
        password = request.form['password']

        # 检查用户名是否已存在
        for user_type_key in users:
            for user in users[user_type_key]:
                if user['username'] == username:
                    return "用户名已存在，请选择其他用户名。"

        # 添加新用户，包含用户的用户名、机号和密码
        users[user_type].append({'username': username, 'machine_id': machine_id, 'password': password, 'class': None})
        return redirect(url_for('register_success'))

    return render_template('register.html')


@app.route('/register_success')
def register_success():
    return render_template('register_success.html')


@app.route('/forgot_password', methods=['GET', 'POST'])
def forgot_password():
    if request.method == 'POST':
        user_type = request.form['user_type']
        username = request.form['username']
        new_password = request.form['new_password']

        # 检查用户类型是否有效
        if user_type not in users:
            return "无效的用户类型。", 400  # 返回错误状态码

        # 查找并更新用户密码
        user_found = False
        for user in users[user_type]:
            if user['username'] == username:
                user['password'] = new_password
                user_found = True
                return redirect(url_for('password_reset_success'))  # 密码重置成功，跳转到成功页面

        # 如果没有找到用户，返回错误信息
        if not user_found:
            return "用户名不存在。", 404

    return render_template('forgot_password.html')


@app.route('/password_reset_success')
def password_reset_success():
    return render_template('password_reset_success.html')


# 学生页面
@app.route('/student_dashboard/<username>', methods=['GET', 'POST'])
def student_dashboard(username):
    if 'user_type' not in session or session['user_type'] != 'student':
        return redirect(url_for('login'))

    if request.method == 'POST':
        class_name = request.form['class_name']
        for student in users['student']:
            if student['username'] == username:
                student['class'] = class_name
                if class_name not in classes:
                    classes[class_name] = []
                classes[class_name].append(username)
                # 成功加入班级后跳转到选择考试页面
                return redirect(url_for('student_class', username=username, class_name=class_name))
    student_class_name = next((student['class'] for student in users['student'] if student['username'] == username), None)
    return render_template('student_dashboard.html', username=username, class_name=student_class_name)


# 学生选择加入考试页面
@app.route('/student_class/<username>/<class_name>', methods=['GET', 'POST'])
def student_class(username, class_name):
    if 'user_type' not in session or session['user_type'] != 'student':
        return redirect(url_for('login'))

    if request.method == 'POST':
        exam_name = request.form.get('exam_name')
        if exam_name in exams and exams[exam_name]['class_name'] == class_name:
            # 检查学生是否已经参加过该考试
            if username in exams[exam_name].get('participants', []):
                return "你已经参加过此考试，不能再次加入。", 403

            # 记录学生参加考试
            if 'participants' not in exams[exam_name]:
                exams[exam_name]['participants'] = []
            exams[exam_name]['participants'].append(username)

            session['exam'] = exams[exam_name]
            session['exam_start_time'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')  # 记录考试开始时间为字符串
            return redirect(url_for('exam_page', class_name=class_name, exam_name=exam_name))
        return "没有找到该考试。"

    # 获取该班级内的考试列表，并排除学生已经参加过的考试
    exam_list = [exam_name for exam_name, exam_info in exams.items()
                 if exam_info['class_name'] == class_name and username not in exam_info.get('participants', [])]

    return render_template('student_class.html', username=username, class_name=class_name, exams=exam_list)


# 考试页面
@app.route('/exam/<class_name>/<exam_name>', methods=['GET', 'POST'])
def exam_page(class_name, exam_name):
    if 'user_type' not in session or session['user_type'] != 'student':
        return redirect(url_for('login'))

    exam = exams.get(exam_name)
    if exam:
        remaining_time = exam['end_time'] - datetime.now()
        if remaining_time.total_seconds() <= 0:
            return "考试时间已到，系统已自动提交。"

        # 计算剩余时间
        remaining_seconds = int(remaining_time.total_seconds())

        return render_template('exam.html', remaining_time=remaining_seconds,
                               class_name=class_name, exam_name=exam_name)
    return "没有找到考试信息。", 404


# 新增的考试完成页面
@app.route('/exam_finished/<class_name>/<exam_name>', methods=['GET'])
def exam_finished(class_name, exam_name):
    if 'user_type' not in session or session['user_type'] != 'student':
        return redirect(url_for('login'))

    # 渲染新的考试完成页面
    return render_template('exam_finished.html', class_name=class_name, exam_name=exam_name, username=session['username'])


@app.route('/submit_exam/<class_name>/<exam_name>', methods=['POST'])
def submit_exam(class_name, exam_name):
    if 'user_type' not in session or session['user_type'] != 'student':
        return redirect(url_for('login'))

    exam = exams.get(exam_name)
    if exam:
        try:
            # 从 session 中获取 exam_start_time，并确保它是 datetime 对象
            exam_start_time_str = session.get('exam_start_time')
            if not exam_start_time_str:
                raise ValueError("考试开始时间未找到")

            # 将字符串转换回 datetime 对象
            exam_start_time = datetime.strptime(exam_start_time_str, '%Y-%m-%d %H:%M:%S.%f')

            # 计算考试用时
            elapsed_time = datetime.now() - exam_start_time
            elapsed_seconds = int(elapsed_time.total_seconds())

            # 删除该学生的考试信息
            session.pop('exam', None)
            session.pop('exam_start_time', None)

            # 渲染考试完成页面，传递考试名称、考试用时、班级名称和用户名
            return render_template('exam_finished.html', class_name=class_name, exam_name=exam_name,
                                   elapsed_seconds=elapsed_seconds, username=session['username'])
        except Exception as e:
            print(f"考试提交时发生错误: {e}")
            return render_template('exam_finished.html', class_name=class_name, exam_name=exam_name, error=str(e),
                                   username=session['username'])
    return "考试提交失败，未找到考试信息。", 404


# 老师页面
@app.route('/teacher_dashboard/<username>', methods=['GET', 'POST'])
def teacher_dashboard(username):
    if 'user_type' not in session or session['user_type'] != 'teacher':
        return redirect(url_for('login'))

    if request.method == 'POST':
        if 'add_exam' in request.form:  # 如果提交的是添加考试请求
            return redirect(url_for('set_exam_time', username=username))

    return render_template('teacher_dashboard.html', username=username)


@app.route('/manage_class/<username>', methods=['GET', 'POST'])
def manage_class(username):
    if 'user_type' not in session or session['user_type'] != 'teacher':
        return redirect(url_for('login'))

    if request.method == 'POST':
        class_name = request.form.get('class_name', '')
        if not class_name:
            return "班级名称不能为空", 400  # Bad request
        # 处理班级管理逻辑
        return redirect(url_for('class_management', class_name=class_name))

    return render_template('teacher_dashboard.html', username=username)


@app.route('/class_management/<class_name>', methods=['GET'])
def class_management(class_name):
    if 'user_type' not in session or session['user_type'] != 'teacher':
        return redirect(url_for('login'))

    students = classes.get(class_name, [])
    # 检查是否有正在进行的考试
    ongoing_exams = [exam_name for exam_name, exam_info in exams.items() if
                     exam_info['class_name'] == class_name and datetime.now() < exam_info['end_time']]

    return render_template('class_management.html', class_name=class_name, students=students,
                           ongoing_exams=ongoing_exams)


# 设置考试时间页面
@app.route('/set_exam_time/<username>', methods=['GET', 'POST'])
def set_exam_time(username):
    if 'user_type' not in session or session['user_type'] != 'teacher':
        return redirect(url_for('login'))

    if request.method == 'POST':
        exam_name = request.form.get('exam_name', '')
        class_name = request.form.get('class_name', '')
        exam_duration = request.form.get('exam_duration', '')
        if not exam_name or not class_name or not exam_duration:
            return "考试名称、班级名称和考试时长不能为空", 400  # Bad request

        # 设置考试时间的逻辑
        end_time = datetime.now() + timedelta(minutes=int(exam_duration))
        exams[exam_name] = {
            'class_name': class_name,
            'start_time': datetime.now(),
            'end_time': end_time,
            'participants': []  # 初始化考试的参与者列表
        }
        session['exam'] = exams[exam_name]

        # 设置考试时间后重定向到题目上传页面
        return redirect(url_for('upload_exam_questions', exam_name=exam_name))

    # 获取班级列表
    class_list = list(classes.keys())

    return render_template('set_exam_time.html', username=username, classes=class_list)


# 家长页面
@app.route('/parent_dashboard/<username>')
def parent_dashboard(username):
    if 'user_type' not in session or session['user_type'] != 'parent':
        return redirect(url_for('login'))

    return render_template('parent_dashboard.html', username=username)


# 上传考试题目
@app.route('/upload_exam_questions/<exam_name>', methods=['GET', 'POST'])
def upload_exam_questions(exam_name):
    if 'user_type' not in session or session['user_type'] != 'teacher':
        return redirect(url_for('login'))

    if request.method == 'POST':
        if 'file' not in request.files or request.files['file'].filename == '':
            return '没有选择文件'

        file = request.files['file']
        question_type = request.form['question_type']

        if file and allowed_file(file.filename):
            filename = os.path.join(app.config['UPLOAD_FOLDER'], file.filename)
            file.save(filename)

            # 调试信息
            print(f"文件已保存到: {filename}")

            # 检查文件是否正确保存
            if not os.path.exists(filename):
                return '文件保存失败'

            try:
                questions = extract_questions(filename, question_type)
                print(f"提取的问题: {questions}")
            except Exception as e:
                print(f"提取问题时发生错误: {e}")
                return '提取问题失败'

            try:
                insert_questions(exam_name, questions, question_type)
            except Exception as e:
                print(f"插入问题时发生错误: {e}")
                return '插入问题失败'

            return redirect(url_for('upload_success'))

        return '文件格式不正确'

    return render_template('upload.html', exam_name=exam_name)


@app.route('/upload_success')
def upload_success():
    return render_template('success.html')


# 记录作弊行为
@app.route('/record_cheating', methods=['POST'])
def record_cheating():
    if 'username' in session:
        username = session['username']
        if username not in cheating_records:
            cheating_records[username] = 0
        cheating_records[username] += 1

        max_cheat_attempts = 2
        if cheating_records[username] > max_cheat_attempts:
            return jsonify({'terminate': True})
        return jsonify({'terminate': False})
    return jsonify({'error': 'User not logged in'}), 401


# 终止考试
@app.route('/terminate_exam')
def terminate_exam():
    session.pop('exam', None)
    return "由于检测到多次作弊行为，您的考试已被终止。", 400


if __name__ == "__main__":
    if not os.path.exists(app.config['UPLOAD_FOLDER']):
        os.makedirs(app.config['UPLOAD_FOLDER'])
    app.run(host='0.0.0.0', port=5000, debug=True)
